// 3种固定状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'

class MPromise {

  // 成功回调数组
  FULFILED_CALLBACK_LIST = []
  REJECTED_CALLBACK_LIST = []

  // 新变量 私有变量
  _status = PENDING
  
  // fn初始化的时候执行
  constructor(fn) {
    // 初始状态 为  pending
    this.status = PENDING
    // fulfilled的值
    this.value = null
    // rejected的值
    this.reason = null

    try {
      fn(this.resolve.bind(this), this.reject.bind(this))
    } catch (e) {
      this.reject(e)
    }

  }

  // todo:了解es6的getter和setter
  get status() {
    // 获取this.status的时候触发
    return this._status
  }

  set status(newStatus) {
    // 给status赋值的时候出发
    // 执行callback_list的回调
    switch (newStatus) {
      case FULFILLED:
        this.FULFILED_CALLBACK_LIST.forEach(callback => {
          callback(this.value)
        })
        break;
      case REJECTED:
        this.REJECTED_CALLBACK_LIST.forEach(callback => {
          callback(this.reason)
        })
        break;
    }
  }

  resolve(value) {
    if(this.status === PENDING) {
      this.value = value
      this.status = FULFILLED
    }
  }

  reject(reason) {
    if (this.status === PENDING) {
      this.reason = reason
      this.status = REJECTED
    }
  }

  then(onFulfilled, onRejected) {
    const realOnfulfilled = this.isFunction(onFulfilled) ? onFulfilled : (value) => value
    const realOnRejected = this.isFunction(onRejected) ? onRejected : reason => {
      throw reason
    }

    // .then 的返回值是一个（新的）promise，并不是当前的实例
    const promise2 = new MPromise((resolve, reject) => {
      // 执行失败的逻辑
      const fulfilledMicrotask = () => {
        try {
          realOnfulfilled(this.value)
        } catch (e) {
          reject(e)
        }
      }

      const rejectedMicrotask = () => {
        try {
          realOnRejected(this.reason)
        } catch (e) {
          reject(e)
        }
      }



      //  根据不同的状态执行不同的操作
      switch (this.status) {
        case FULFILLED:
          // realOnfulfilled()
          fulfilledMicrotask()
          break;
        case REJECTED:
          // realOnRejected()
          rejectedMicrotask()
          break;
        case PENDING:
          // 处理异步操作的时候 比如setTimeOut 这里状态还没改变 所以需要用数组存起来  等状态改变的时候再去循环执行回调
          // 新建2个数组存储成功和失败的回调 FULFILLED_CALLBACK_LIST REJECTED_CALLBACK_LIST
          this.FULFILED_CALLBACK_LIST.push(realOnfulfilled)
          this.REJECTED_CALLBACK_LIST.push(realOnRejected)
          // ??存储之后什么时候去执行呢??
          // 当status发生变化的时候执行
          break;
      }
    });
    return promise2
  }

  // 判断是不是一个函数
  isFunction(param) {
    return typeof param === 'function'
  }

}